package devstar_devcontainer

import (
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/setting"
	gitea_web_context "code.gitea.io/gitea/services/context"
	"code.gitea.io/gitea/services/devstar_devcontainer/docker_agent"
	devcontainer_service_errors "code.gitea.io/gitea/services/devstar_devcontainer/errors"
	k8s_agent_services "code.gitea.io/gitea/services/devstar_devcontainer/k8s_agent"
	devcontainer_service_options "code.gitea.io/gitea/services/devstar_devcontainer/options"
	devcontainer_service_vo "code.gitea.io/gitea/services/devstar_devcontainer/vo"
)

// OpenDevcontainerService 获取 DevContainer 连接信息，抽象方法，适配多种 DevContainer Agent
func OpenDevcontainerService(ctx *gitea_web_context.Context, opts *devcontainer_service_options.OpenDevcontainerAppDispatcherOptions) (*devcontainer_service_vo.OpenDevcontainerAbstractAgentVO, error) {

	// 0. 检查参数
	if ctx == nil || opts == nil || len(opts.Name) == 0 {
		return nil, devcontainer_service_errors.ErrIllegalParams{
			FieldNameList: []string{"ctx", "opts.Name"},
		}
	}

	// 1. 检查 DevContainer 功能是否开启
	if setting.Devstar.Devcontainer.Enabled == false {
		return nil, devcontainer_service_errors.ErrOperateDevcontainer{
			Action:  "check availability of DevStar DevContainer",
			Message: "DevContainer is turned off globally",
		}
	}

	// 2. 根据 DevContainer Agent 类型分发任务
	apiRequestContext := ctx.Req.Context()
	openDevcontainerAbstractAgentVO := &devcontainer_service_vo.OpenDevcontainerAbstractAgentVO{}
	switch setting.Devstar.Devcontainer.Agent {
	case setting.DEVCONTAINER_AGENT_NAME_K8S:
		devcontainerApp, err := k8s_agent_services.AssignDevcontainerGetting2K8sOperator(&apiRequestContext, opts)
		if err != nil {
			return nil, devcontainer_service_errors.ErrOperateDevcontainer{
				Action:  "Open DevContainer in k8s",
				Message: err.Error(),
			}
		}
		openDevcontainerAbstractAgentVO.NodePortAssigned = devcontainerApp.Status.NodePortAssigned
	case setting.DEVCONTAINER_AGENT_NAME_DOCKER:
		port, err := docker_agent.AssignDevcontainerGettingDockerOperator(&apiRequestContext, opts)
		log.Info("port %d", port)
		if err != nil {
			return nil, devcontainer_service_errors.ErrOperateDevcontainer{
				Action:  "Open DevContainer in docker",
				Message: err.Error(),
			}
		}
		openDevcontainerAbstractAgentVO.NodePortAssigned = port
	default:
		return nil, devcontainer_service_errors.ErrOperateDevcontainer{
			Action:  "Open DevContainer",
			Message: "No Valid DevContainer Agent Found",
		}
	}

	// 3. 封装返回结果
	return openDevcontainerAbstractAgentVO, nil
}
